/* eslint-disable @typescript-eslint/no-explicit-any */
import { MetadataKey } from './enum';
import { Constructor } from './interfaces';
import { isArray, isString } from './utils';

const assignMetadata = <TParamtype = any, TArgs = any>(
    args: TArgs,
    paramtype: TParamtype,
    index: number,
    data?: any,
    pipes?: Array<Constructor<any> | object>,
): Record<string, any> => {
    return {
        ...args,
        // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
        [`${paramtype}:${index}`]: {
            index,
            data,
            pipes,
        },
    };
};

export function Param(property?: string | string[], ...pipes: Array<Constructor<any> | object>) {
    return function (target: any, propertyKey: string, index: number) {
        const args = Reflect.getMetadata(MetadataKey.ROUTE_ARGS_METADATA, target.constructor, propertyKey) || {};
        const hasParamData = isString(property) || isArray(property);
        const paramData = hasParamData ? property : void 0;
        Reflect.defineMetadata(MetadataKey.METADATATYPE, 'param', target.constructor, propertyKey);
        Reflect.defineMetadata(
            MetadataKey.ROUTE_ARGS_METADATA,
            assignMetadata(args, 0, index, paramData, pipes),
            target.constructor,
            propertyKey,
        );
    };
}
